#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
SQL文件合并工具
按照文件名的版本号顺序（如 V1.0, V1.1, V2.0 等）读取并合并指定目录下的所有SQL文件
"""

import os
import re
from pathlib import Path
from typing import List, Tuple


def extract_version(filename: str) -> Tuple[int, ...]:
    """
    从文件名中提取版本号
    
    例如: V1.0__xxx.sql -> (1, 0)
          V2.10__xxx.sql -> (2, 10)
          V3.1.2__xxx.sql -> (3, 1, 2)
    
    Args:
        filename: 文件名
        
    Returns:
        版本号元组，用于排序
    """
    # 匹配 V 后面的数字和点号
    match = re.match(r'^V([\d.]+)', filename)
    if match:
        version_str = match.group(1)
        # 将版本号拆分为整数元组
        return tuple(int(x) for x in version_str.split('.'))
    # 如果没有匹配到版本号，返回一个很大的数字，排在最后
    return (999999,)


def get_sql_files(directory: str) -> List[str]:
    """
    获取指定目录下的所有SQL文件并按版本号排序
    
    Args:
        directory: 目录路径
        
    Returns:
        排序后的SQL文件路径列表
    """
    sql_files = []
    dir_path = Path(directory)
    
    if not dir_path.exists():
        raise FileNotFoundError(f"目录不存在: {directory}")
    
    if not dir_path.is_dir():
        raise NotADirectoryError(f"路径不是目录: {directory}")
    
    # 获取所有.sql文件
    for file_path in dir_path.glob('*.sql'):
        if file_path.is_file():
            sql_files.append(str(file_path))
    
    # 按版本号排序
    sql_files.sort(key=lambda x: extract_version(os.path.basename(x)))
    
    return sql_files


def merge_sql_files(input_directory: str, output_file: str, add_separator: bool = True):
    """
    合并SQL文件
    
    Args:
        input_directory: 输入目录路径
        output_file: 输出文件路径
        add_separator: 是否在文件之间添加分隔符
    """
    sql_files = get_sql_files(input_directory)
    
    if not sql_files:
        print(f"警告: 在目录 {input_directory} 中没有找到SQL文件")
        return
    
    print(f"找到 {len(sql_files)} 个SQL文件:")
    for idx, file_path in enumerate(sql_files, 1):
        print(f"  {idx}. {os.path.basename(file_path)}")
    
    print(f"\n开始合并到: {output_file}")
    
    with open(output_file, 'w', encoding='utf-8') as outfile:
        # 写入文件头注释
        outfile.write("-- ============================================\n")
        outfile.write("-- SQL文件合并结果\n")
        outfile.write(f"-- 生成时间: {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
        outfile.write(f"-- 源目录: {input_directory}\n")
        outfile.write(f"-- 文件数量: {len(sql_files)}\n")
        outfile.write("-- ============================================\n\n")
        
        for idx, file_path in enumerate(sql_files, 1):
            filename = os.path.basename(file_path)
            
            if add_separator:
                # 添加文件分隔符
                outfile.write("\n")
                outfile.write("-- ============================================\n")
                outfile.write(f"-- 文件 {idx}/{len(sql_files)}: {filename}\n")
                outfile.write("-- ============================================\n\n")
            
            # 读取并写入文件内容
            try:
                with open(file_path, 'r', encoding='utf-8') as infile:
                    content = infile.read()
                    outfile.write(content)
                    
                    # 确保文件内容以换行符结尾
                    if content and not content.endswith('\n'):
                        outfile.write('\n')
                
                print(f"  ✓ 已合并: {filename}")
            except Exception as e:
                print(f"  ✗ 读取失败: {filename} - {str(e)}")
                raise
        
        outfile.write("\n-- ============================================\n")
        outfile.write("-- 合并完成\n")
        outfile.write("-- ============================================\n")
    
    print(f"\n✓ 合并完成! 输出文件: {output_file}")
    
    # 显示输出文件大小
    file_size = os.path.getsize(output_file)
    if file_size < 1024:
        size_str = f"{file_size} B"
    elif file_size < 1024 * 1024:
        size_str = f"{file_size / 1024:.2f} KB"
    else:
        size_str = f"{file_size / (1024 * 1024):.2f} MB"
    print(f"  文件大小: {size_str}")


def main():
    """主函数"""
    import argparse
    
    parser = argparse.ArgumentParser(
        description='按版本号顺序合并SQL文件',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
使用示例:
  # 合并当前目录下的SQL文件
  python merge_sql_files.py -i ./sql -o merged.sql
  
  # 合并项目中的Flyway迁移文件
  python merge_sql_files.py -i ./migration -o merged_migration.sql
  
  # 不添加分隔符
  python merge_sql_files.py -i ./sql -o merged.sql --no-separator
        """
    )
    
    parser.add_argument(
        '-i', '--input',
        type=str,
        default='./migration',
        help='输入目录路径 (默认: ./migration)'
    )
    
    parser.add_argument(
        '-o', '--output',
        type=str,
        default='merged_migration.sql',
        help='输出文件路径 (默认: merged_migration.sql)'
    )
    
    parser.add_argument(
        '--no-separator',
        action='store_true',
        help='不在文件之间添加分隔符注释'
    )
    
    args = parser.parse_args()
    
    try:
        merge_sql_files(
            input_directory=args.input,
            output_file=args.output,
            add_separator=not args.no_separator
        )
    except Exception as e:
        print(f"\n错误: {str(e)}")
        exit(1)


if __name__ == '__main__':
    main()
